package org.javahispano.javacup.tacticas_aceptadas.willBender.will.team.tactica;

import java.awt.Color;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.javahispano.javacup.modelo.Comando;
import org.javahispano.javacup.modelo.ComandoIrA;
import org.javahispano.javacup.modelo.Constantes;
import org.javahispano.javacup.modelo.EstiloUniforme;
import org.javahispano.javacup.modelo.JugadorDetalle;
import org.javahispano.javacup.modelo.Posicion;
import org.javahispano.javacup.modelo.SituacionPartido;
import org.javahispano.javacup.modelo.Tactica;
import org.javahispano.javacup.modelo.TacticaDetalle;

import org.javahispano.javacup.tacticas_aceptadas.willBender.will.team.UtilWill;
import org.javahispano.javacup.tacticas_aceptadas.willBender.will.team.players.Armador10Will;
import org.javahispano.javacup.tacticas_aceptadas.willBender.will.team.players.Armador9Will;
import org.javahispano.javacup.tacticas_aceptadas.willBender.will.team.players.ArqueroWill;
import org.javahispano.javacup.tacticas_aceptadas.willBender.will.team.players.Defensa2Will;
import org.javahispano.javacup.tacticas_aceptadas.willBender.will.team.players.Defensa3Will;
import org.javahispano.javacup.tacticas_aceptadas.willBender.will.team.players.Defensa5Will;
import org.javahispano.javacup.tacticas_aceptadas.willBender.will.team.players.Goleador11Will;
import org.javahispano.javacup.tacticas_aceptadas.willBender.will.team.players.Lateral4Will;
import org.javahispano.javacup.tacticas_aceptadas.willBender.will.team.players.Lateral8Will;
import org.javahispano.javacup.tacticas_aceptadas.willBender.will.team.players.Recuperador6Will;
import org.javahispano.javacup.tacticas_aceptadas.willBender.will.team.players.Recuperador7Will;
import org.javahispano.javacup.tacticas_aceptadas.willBender.will.team.players.WillTeamPlayer;

public class WillTeam implements Tactica {

	Posicion alineacion1[] = new Posicion[] {
			new Posicion(0.2595419847328244, -50.41044776119403),
			new Posicion(-26.153846153846157, -28.50678733031674),
			new Posicion(-9.272727272727272, -31.119909502262445),
			new Posicion(9.272727272727272, -31.59502262443439),
			new Posicion(25.44055944055944, -28.50678733031674),
			new Posicion(17.11888111888112, -11.402714932126697),
			new Posicion(-19.97202797202797, -11.402714932126697),
			new Posicion(-0.7132867132867133, -13.540723981900454),
			new Posicion(8.083916083916083, 22.092760180995477),
			new Posicion(-6.895104895104895, 9.502262443438914),
			new Posicion(0.0, 37.53393665158371) };

	Posicion alineacion5[] = new Posicion[] {
			new Posicion(0.2595419847328244, -50.41044776119403),
			new Posicion(-11.16030534351145, -35.78358208955224),
			new Posicion(12.717557251908397, -35.26119402985075),
			new Posicion(28.290076335877863, -28.470149253731343),
			new Posicion(-28.290076335877863, -28.470149253731343),
			new Posicion(14.793893129770993, -18.544776119402986),
			new Posicion(-17.389312977099234, -19.58955223880597),
			new Posicion(-23.618320610687025, -0.7835820895522387),
			new Posicion(5.969465648854961, -5.485074626865671),
			new Posicion(0.2595419847328244, -0.26119402985074625),
			new Posicion(22.580152671755727, -1.3059701492537314) };

	Posicion alineacion6[] = new Posicion[] {
			new Posicion(0.2595419847328244, -50.41044776119403),
			new Posicion(-11.16030534351145, -35.78358208955224),
			new Posicion(12.717557251908397, -35.26119402985075),
			new Posicion(28.290076335877863, -28.470149253731343),
			new Posicion(-28.290076335877863, -28.470149253731343),
			new Posicion(14.793893129770993, -18.544776119402986),
			new Posicion(-17.389312977099234, -19.58955223880597),
			new Posicion(-23.618320610687025, -0.7835820895522387),
			new Posicion(6.4885496183206115, -6.529850746268657),
			new Posicion(-6.4885496183206115, -6.529850746268657),
			new Posicion(22.580152671755727, -1.3059701492537314) };

	class TacticaDetalleImpl implements TacticaDetalle {

		public String getNombre() {
			return "WillTeam";
		}

		public String getPais() {
			return "Colombia";
		}

		public String getEntrenador() {
			return "WillBender";
		}

		public Color getColorCamiseta() {
			return new Color(204, 0, 0);
		}

		public Color getColorPantalon() {
			return new Color(0, 51, 204);
		}

		public Color getColorFranja() {
			return new Color(255, 255, 255);
		}

		public Color getColorCalcetas() {
			return new Color(255, 255, 255);
		}

		public Color getColorPortero() {
			return new Color(0, 0, 0);
		}

		public EstiloUniforme getEstilo() {
			return EstiloUniforme.LINEAS_VERTICALES;
		}

		public Color getColorCamiseta2() {
			return new Color(51, 51, 51);
		}

		public Color getColorPantalon2() {
			return new Color(255, 0, 0);
		}

		public Color getColorFranja2() {
			return new Color(255, 255, 255);
		}

		public Color getColorCalcetas2() {
			return new Color(0, 0, 204);
		}

		public Color getColorPortero2() {
			return new Color(255, 204, 0);
		}

		public EstiloUniforme getEstilo2() {
			return EstiloUniforme.FRANJA_HORIZONTAL;
		}

		class JugadorImpl implements JugadorDetalle {

			String nombre;
			int numero;
			Color piel, pelo;
			double velocidad, remate, presicion;
			boolean portero;
			Posicion posicion;

			public JugadorImpl(String nombre, int numero, Color piel,
					Color pelo, double velocidad, double remate,
					double presicion, boolean portero) {
				this.nombre = nombre;
				this.numero = numero;
				this.piel = piel;
				this.pelo = pelo;
				this.velocidad = velocidad;
				this.remate = remate;
				this.presicion = presicion;
				this.portero = portero;
			}

			public String getNombre() {
				return nombre;
			}

			public Color getColorPiel() {
				return piel;
			}

			public Color getColorPelo() {
				return pelo;
			}

			public int getNumero() {
				return numero;
			}

			public boolean esPortero() {
				return portero;
			}

			public double getVelocidad() {
				return velocidad;
			}

			public double getRemate() {
				return remate;
			}

			public double getPresicion() {
				return presicion;
			}

		}

		public JugadorDetalle[] getJugadores() {
			return new JugadorDetalle[] {
					new JugadorImpl("Chilavert", 1, new Color(255, 200, 150),
							new Color(50, 0, 0), 1.0d, 0.74d, 0.5d, true),
					new JugadorImpl("Gamarra", 2, new Color(255, 200, 150),
							new Color(50, 0, 0), 1.0d, 0.69d, 0.69d, false),
					new JugadorImpl("Yepes", 3, new Color(255, 200, 150),
							new Color(50, 0, 0), 1.0d, 0.92d, 0.9d, false),
					new JugadorImpl("Escobar", 4, new Color(255, 200, 150),
							new Color(50, 0, 0), 1.0d, 0.76d, 0.72d, false),
					new JugadorImpl("Larsson", 5, new Color(255, 200, 150),
							new Color(50, 0, 0), 1.0d, 0.74d, 0.71d, false),
					new JugadorImpl("Alvarez", 6, new Color(255, 200, 150),
							new Color(50, 0, 0), 1.0d, 0.73d, 0.69d, false),
					new JugadorImpl("Gerrard", 7, new Color(255, 200, 150),
							new Color(50, 0, 0), 1.0d, 0.76d, 0.68d, false),
					new JugadorImpl("Rincon", 8, new Color(255, 200, 150),
							new Color(50, 0, 0), 1.0d, 0.76d, 0.77d, false),
					new JugadorImpl("Kaka", 9, new Color(255, 200, 150),
							new Color(50, 0, 0), 1.0d, 0.89d, 0.89d, false),
					new JugadorImpl("Valderrama", 10, new Color(255, 200, 150),
							new Color(50, 0, 0), 1.0d, 0.67d, 0.9d, false),
					new JugadorImpl("Angel", 11, new Color(255, 200, 150),
							new Color(50, 0, 0), 1.0d, 0.69d, 0.7d, false) };
		}
	}

	TacticaDetalle detalle = new TacticaDetalleImpl();

	public TacticaDetalle getDetalle() {
		return detalle;
	}

	public Posicion[] getPosicionSaca(SituacionPartido sp) {
		return alineacion5;
	}

	public Posicion[] getPosicionRecive(SituacionPartido sp) {
		return alineacion6;
	}

	WillTeamPlayer chilavert = new ArqueroWill();
	WillTeamPlayer gamarra = new Defensa2Will();
	WillTeamPlayer yepes = new Defensa3Will();
	WillTeamPlayer escobar = new Lateral4Will();
	WillTeamPlayer larsson = new Defensa5Will();
	WillTeamPlayer alvarez = new Recuperador6Will();
	WillTeamPlayer gerard = new Recuperador7Will();
	WillTeamPlayer rincon = new Lateral8Will();
	WillTeamPlayer kaka = new Armador9Will();
	WillTeamPlayer valderrama = new Armador10Will();
	WillTeamPlayer angel = new Goleador11Will();
	Posicion balonPasado = new Posicion();
	double heightAnt = 0;
	// Marcas (mi jugador, rival)
	Map<Integer, Integer> marcas = new HashMap<Integer, Integer>();
	int iteracionesSaque = 0;

	public List<Comando> ejecutar(SituacionPartido sp) {
		List<Comando> comandosWill = new ArrayList<Comando>();
		if (defender(sp)) {
			marcas = asignarMarcas(sp);
			Posicion[] rivales = sp.rivales();
			for (Iterator<Integer> iterator = marcas.keySet().iterator(); iterator
					.hasNext();) {
				Integer jug = iterator.next();

				double angulo = rivales[marcas.get(jug)]
						.angulo(Constantes.centroArcoInf);
				Posicion posMarca = rivales[marcas.get(jug)]
						.moverAngulo(angulo, getDistanciaMarca(sp,
								rivales[marcas.get(jug)]));
				comandosWill.add(new ComandoIrA(jug, posMarca));
			}
		} else {
			marcas = new HashMap<Integer, Integer>();

		}
		chilavert.getComandosJugador().clear();
		chilavert.getMejorOpcion(sp);
		comandosWill.addAll(chilavert.getComandosJugador());
		gamarra.getComandosJugador().clear();
		gamarra.getMejorOpcion(sp);
		comandosWill.addAll(gamarra.getComandosJugador());
		yepes.getComandosJugador().clear();
		yepes.getMejorOpcion(sp);
		comandosWill.addAll(yepes.getComandosJugador());
		escobar.getComandosJugador().clear();
		escobar.getMejorOpcion(sp);
		comandosWill.addAll(escobar.getComandosJugador());
		larsson.getComandosJugador().clear();
		larsson.getMejorOpcion(sp);
		comandosWill.addAll(larsson.getComandosJugador());
		alvarez.getComandosJugador().clear();
		alvarez.getMejorOpcion(sp);
		comandosWill.addAll(alvarez.getComandosJugador());
		gerard.getComandosJugador().clear();
		gerard.getMejorOpcion(sp);
		comandosWill.addAll(gerard.getComandosJugador());
		rincon.getComandosJugador().clear();
		rincon.getMejorOpcion(sp);
		comandosWill.addAll(rincon.getComandosJugador());
		kaka.getComandosJugador().clear();
		kaka.getMejorOpcion(sp);
		comandosWill.addAll(kaka.getComandosJugador());
		valderrama.getComandosJugador().clear();
		valderrama.getMejorOpcion(sp);
		comandosWill.addAll(valderrama.getComandosJugador());
		angel.getComandosJugador().clear();
		angel.getMejorOpcion(sp);
		comandosWill.addAll(angel.getComandosJugador());
		// for (int i : sp.puedenRematar()) {
		// if ((sp.misJugadores()[i]
		// .distancia(sp.rivales()[sp.misJugadores()[i]
		// .indiceMasCercano(sp.rivales())]) < ConstantesWill.distanciaMinima)
		// && (sp.misJugadores()[i].getY() < sp.rivales()[sp
		// .misJugadores()[i].indiceMasCercano(sp.rivales())]
		// .getY())) {
		// double ang = sp.misJugadores()[i].angulo(sp.rivales()[sp
		// .misJugadores()[i].indiceMasCercano(sp.rivales())]);
		// comandosWill.add(new ComandoGolpearBalon(i, -ang, 1d, true));
		// } else {
		// comandosWill.add(new ComandoGolpearBalon(i,
		// Constantes.centroArcoSup, 1.0, true));
		// }
		// }
		comandosWill.add(new ComandoIrA(0, UtilWill.getPosicionArquero(
				sp.balon(), balonPasado).setDentroCampoJuego()));
		Posicion posNextBalon = UtilWill.getBalonCercano(sp, balonPasado,
				heightAnt).setDentroCampoJuego();
		int masCercano = posNextBalon.indiceMasCercano(sp.misJugadores());
		if (posibilidadBalon(sp) && (masCercano != 0 || sp.alturaBalon() < 0.2)) {
			comandosWill.add(new ComandoIrA(masCercano, posNextBalon));
		}
		if (sp.saco()) {
			if (sp.balon().getY() < -12) {
				if (iteracionesSaque > 30) {
					masCercano = sp.balon().indiceMasCercano(sp.misJugadores());
					comandosWill.add(new ComandoIrA(masCercano, sp.balon()));
				}
				iteracionesSaque++;
			} else {
				masCercano = sp.balon().indiceMasCercano(sp.misJugadores());
				comandosWill.add(new ComandoIrA(masCercano, sp.balon()));
			}
		} else {
			iteracionesSaque = 0;
		}
		if (sp.sacaRival()) {
			int rivalMasCercano = sp.balon().indiceMasCercano(sp.rivales());
			int mioMasCercano = sp.rivales()[rivalMasCercano]
					.indiceMasCercano(sp.misJugadores());
			double angulo = sp.rivales()[rivalMasCercano]
					.angulo(Constantes.centroArcoInf);
			Posicion posMarca = sp.rivales()[rivalMasCercano].moverAngulo(
					angulo, Constantes.DISTANCIA_SAQUE + 1);
			comandosWill.add(new ComandoIrA(mioMasCercano, posMarca));
		}
		balonPasado = sp.balon().setDentroCampoJuego();
		heightAnt = sp.alturaBalon();
		return comandosWill;

	}

	private double getDistanciaMarca(SituacionPartido sp, Posicion posicion) {
		return 2.4;
	}

	private Map<Integer, Integer> asignarMarcas(SituacionPartido sp) {
		if (marcas.isEmpty()) {
			Posicion[] rivales = sp.rivales();
			int[] masCercanosArco = Constantes.centroArcoInf
					.indicesMasCercanos(rivales);
			ArrayList<Integer> asignados = new ArrayList<Integer>();
			for (int i = 0; i < masCercanosArco.length; i++) {
				int[] masCercanos = rivales[masCercanosArco[i]]
						.indicesMasCercanos(sp.misJugadores());
				for (int j = 0; j < masCercanos.length; j++) {
					if (!asignados.contains(masCercanos[j])
							&& masCercanos[j] != 0) {
						marcas.put(masCercanos[j], masCercanosArco[i]);
						asignados.add(masCercanos[j]);
						break;
					}
				}
			}
		}
		return marcas;
	}

	private boolean defender(SituacionPartido sp) {
		int rematar = sp.puedenRematar().length;
		int masCercanoMio = sp.balon().indiceMasCercano(sp.misJugadores());
		double distMia = sp.balon().distancia(sp.misJugadores()[masCercanoMio]);
		int masCercanoRiv = sp.balon().indiceMasCercano(sp.rivales());
		double distRiv = sp.balon().distancia(sp.rivales()[masCercanoRiv]);
		if (sp.balon().getY() < 15 || (rematar == 0 && distRiv < distMia))
			return true;
		return false;
	}

	private boolean posibilidadBalon(SituacionPartido sp) {
		int rematar = sp.puedenRematar().length;
		Posicion posNextBalon = UtilWill.getBalonCercano(sp, balonPasado,
				heightAnt).setDentroCampoJuego();
		int masCercanoMio = posNextBalon.indiceMasCercano(sp.misJugadores());
		double distMia = posNextBalon
				.distancia(sp.misJugadores()[masCercanoMio]);
		int masCercanoRiv = posNextBalon.indiceMasCercano(sp.rivales());
		double distRiv = posNextBalon.distancia(sp.rivales()[masCercanoRiv]);
		if (rematar == 0 && distRiv >= distMia)
			return true;
		return false;
	}
}